package com.hy.security.security;


import com.alibaba.fastjson2.JSONObject;
import com.hy.common.base.RespResult;
import com.hy.common.consts.RedisConst;
import com.hy.common.log.dto.SysOpLogReqDTO;
import com.hy.common.log.eventbus.EventBusFactory;
import com.hy.common.log.eventbus.SysOpLogEvent;
import com.hy.common.log.eventbus.SysOpLogEventBusListener;
import com.hy.common.utils.IPUtil;
import com.hy.entity.vo.HyUserVO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * 退出处理
 */
public class TokenLogoutHandler implements LogoutHandler {
    private TokenHandler tokenHandler;
    private RedisTemplate redisTemplate;
    //通过构造方法注入tokenHandler
    public TokenLogoutHandler(TokenHandler tokenHandler,RedisTemplate redisTemplate) {
        this.tokenHandler = tokenHandler;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
         //1. 从header里面获取token
        String token =  request.getHeader("Authorization");
        if(token != null) {
            //从token获取用户名
            String username = tokenHandler.getUserInfoFromToken(token);
            //从redis获取对应权限列表
            HyUserVO currentUserInfo = (HyUserVO) redisTemplate.opsForValue().get(RedisConst.USER_INFO + username);
            SysOpLogReqDTO sysOpLogReqDTO=new SysOpLogReqDTO();
            sysOpLogReqDTO.setMenuName("退出登录");
            sysOpLogReqDTO.setMenuBtn("退出系统");
            sysOpLogReqDTO.setUrl(request.getRequestURI());
            sysOpLogReqDTO.setClassName("DefaultLoginOut");
            sysOpLogReqDTO.setMethodName("LogOut");
            sysOpLogReqDTO.setReqType("GET");
            sysOpLogReqDTO.setParams("无");
            sysOpLogReqDTO.setSuccess(true);
            sysOpLogReqDTO.setResult("退出成功！");
            sysOpLogReqDTO.setOpTime(new Date());
            sysOpLogReqDTO.setOpAccount(currentUserInfo.getPhone() +"("+currentUserInfo.getUsername()+")");
            sysOpLogReqDTO.setOpContent("退出成功！！");
            sysOpLogReqDTO.setOpIp(IPUtil.getIpAddress(request));
            // 发布异步事件
            EventBusFactory.build().registerAsyncEvent(SysOpLogEventBusListener.class);
            EventBusFactory.build().postAsyncEvent(SysOpLogEvent.builder()
                    .sysOpLogReqDTO(sysOpLogReqDTO).eventName("后台操作日志发布事件").build());
            //2. token不为空，从redis删除token
            if(token != null && !"".equals(token)){
                //从token获取用户名
                String username1 = tokenHandler.getUserInfoFromToken(token);
                redisTemplate.delete(RedisConst.PERMISSION_INFO+username1);
                redisTemplate.delete(RedisConst.USER_INFO+username1);
            }

            response.setContentType("application/json;charset=utf-8");
            Map result = new HashMap<>();
            result.put("code",200);
            result.put("msg","退出登录");
            try {
                response.getWriter().write(JSONObject.toJSONString(result));
                response.getWriter().flush();
                response.getWriter().close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else {
            try {
                response.getWriter().write(JSONObject.toJSONString(RespResult.error(500,"没有token、失败！")));
                response.getWriter().flush();
                response.getWriter().close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
